package com.smartResponse;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Color;

import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class AudioService extends Service {
	EventDB db = new EventDB(this);
	int requestCode = 1;
	//The following variables are used to identify location
	private static double MINIMUM_DISTANCECHANGE_FOR_UPDATE = 2; // in Meters
	private static long MINIMUM_TIME_BETWEEN_UPDATE = 15000; // in Milliseconds
	private LocationManager locationManager;
	private static float radius = 0;
	private String proximityIntentAction = new String("seniorDesign.smartResponse.ProximityAlert");
	ProximityIntentReceiver receiver = new ProximityIntentReceiver();
	boolean registerStatus = false;
	public static void Power_Consumption(long time, double distance){
		MINIMUM_DISTANCECHANGE_FOR_UPDATE = distance;
		MINIMUM_TIME_BETWEEN_UPDATE = time;
	 }
	//stored location variables
	long id = 0;
	String l_audio = "";
	String l_name = "";
	int getRinger;
	int getVolume;
	@Override
	public void onCreate(){
		super.onCreate();
		Log.d("onCreate()","Service Created");
		getRingerMode();
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Log.d("distance","Distance: " + MINIMUM_DISTANCECHANGE_FOR_UPDATE );
        Log.d("time","Time: " + MINIMUM_TIME_BETWEEN_UPDATE );
        locationManager.requestLocationUpdates(
                		LocationManager.GPS_PROVIDER, 
                		MINIMUM_TIME_BETWEEN_UPDATE, 
                		(float) MINIMUM_DISTANCECHANGE_FOR_UPDATE,
                		new MyLocationListener()
        );

	}
	@Override
	public void onStart(Intent intent, int startId){
		super.onStart(intent, startId);
		Log.d("onStart()","Service Started");

		RunEnabledLocations();
	}
	@Override
	public void onDestroy(){
		super.onDestroy();
		if (registerStatus == true){
			    try {
			    	restoreRingerMode();
			    	unregisterReceiver(receiver);
			    	registerStatus = false;
			    	Log.d("onDestroy()","Service Destroyed");
			    } catch (IllegalArgumentException e){
			    }
		}

	}
	@Override
	public IBinder onBind(Intent intent) {
		
		return null;
	}
	//Below is the code to set the phone to Ringer
	public void getRingerMode() {
	//Audio Restoration
    AudioManager manager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
    getRinger = manager.getRingerMode();
    if (getRinger == 2){
        getVolume = manager.getStreamVolume(AudioManager.STREAM_RING);
    }
	}
	public void restoreRingerMode(){
	//	getRingerMode();
		if (getRinger == 0){
			setSilent();
		}
		if (getRinger == 1){
			setVibrate();
		}
		if (getRinger == 2){
			setRinger(getVolume);
		}
	}
	//Below is the code to set the phone to Ringer
	public void setRinger(int value) {
		//the value ranges from 0-7 (lowest - highest)
	    AudioManager manager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
	    manager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
	    manager.setStreamVolume(AudioManager.STREAM_RING, value, AudioManager.FLAG_PLAY_SOUND);
	}
	//Below is the code to set the phone to Silent
	public void setSilent() {
	    AudioManager manager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
	    manager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
	    manager.setStreamVolume(AudioManager.STREAM_RING, 0, AudioManager.FLAG_SHOW_UI);
	}
	//Below is the code to set the phone to Vibrate
	public void setVibrate() {
	    AudioManager manager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
	    manager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
	    manager.setStreamVolume(AudioManager.STREAM_RING, 0, AudioManager.FLAG_VIBRATE);
	}

	public void RunEnabledLocations(){
		db.open();
        Cursor c = db.getAllLocations();
		//finds the record in the database from a location name
        while (c.moveToNext())
        {
            String results = c.getString(7); 

			if(results.equals("Enabled"))
			{	
				id = c.getLong(0);
				l_name = c.getString(1);
				l_audio = c.getString(6);
			radius = (float) ((Float.valueOf(c.getString(5)))*0.3048);
			saveProximityAlertPoint(Double.valueOf(c.getString(4)).doubleValue(), Double.valueOf(c.getString(3)).doubleValue());
			Log.d("RunEnabledLocations()",c.getString(1)+" is enabled");
			}
        }
        db.close();
        //end lookup
	}
	
	  private void saveProximityAlertPoint(double latitude, double longitude) {
	    	saveCoordinatesInPreferences((float)latitude, (float)longitude);
	    	addProximityAlert(latitude, longitude);
			Log.d("saveProximityAlertPoint()","saveProximityAlertPoint worked "+(float)latitude);
		}

		private void addProximityAlert(double latitude, double longitude) {
			

	        Intent intent = new Intent(proximityIntentAction);
			intent.putExtra("Name", l_name);
			intent.putExtra("Audio", l_audio);
	        intent.setData(Uri.parse("code://" + requestCode));
	        PendingIntent proximityIntent = PendingIntent.getBroadcast(AudioService.this, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);
	        
	        locationManager.addProximityAlert(
	    		latitude, // the latitude of the central point of the alert region
	    		longitude, // the longitude of the central point of the alert region
	    		radius, // the radius of the central point of the alert region, in meters
	    		-1, // time for this proximity alert, in milliseconds, or -1 to indicate no expiration 
	    		proximityIntent // will be used to generate an Intent to fire when entry to or exit from the alert region is detected
	       );
	        requestCode++;
		       IntentFilter filter = new IntentFilter(proximityIntentAction);
		       filter.addDataScheme("code");
		       registerReceiver(receiver, filter);
		       registerStatus = true;
			Log.d("addProximityAlert()","addProximityAlert worked" + latitude);
	       
		}

	    private void saveCoordinatesInPreferences(float latitude, float longitude) {
	    	SharedPreferences prefs = this.getSharedPreferences(getClass().getSimpleName(), Context.MODE_WORLD_READABLE);
	    	SharedPreferences.Editor prefsEditor = prefs.edit();
	    	prefsEditor.putFloat("Current_Latitude", latitude);
	    	prefsEditor.putFloat("Current_Longitude", longitude);
	    	prefsEditor.commit();
	    }
	    
	    private Location retrievelocationFromPreferences() {
	    	SharedPreferences prefs = this.getSharedPreferences(getClass().getSimpleName(), Context.MODE_WORLD_READABLE);
	    	Location location = new Location("POINT_LOCATION");
	    	location.setLatitude(prefs.getFloat("Current_Latitude", 0));
	    	location.setLongitude(prefs.getFloat("Current_Longitude", 0));
	    	return location;
	    }
    public class MyLocationListener implements LocationListener {
    	public void onLocationChanged(Location location) {
    		Location pointLocation = retrievelocationFromPreferences();
    		//distance is in meters
    		@SuppressWarnings("unused")
			float distance = location.distanceTo(pointLocation);
    	}
    	public void onStatusChanged(String s, int i, Bundle b) {			
    	}
    	public void onProviderDisabled(String s) {
    	}
    	public void onProviderEnabled(String s) {			
    	}
    }
    public class ProximityIntentReceiver extends BroadcastReceiver {

    	private static final int NOTIFICATION_ID = 1000;

    	@Override
    	public void onReceive(Context context, Intent intent) {
    		
    		String key = LocationManager.KEY_PROXIMITY_ENTERING;
    		String name = intent.getStringExtra("Name");
    		String audio = intent.getStringExtra("Audio");
    		Boolean entering = intent.getBooleanExtra(key, false);
    		
    		NotificationManager notificationManager = 
    				(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    		
    		Notification notification = createNotification();
    		
    		PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, null, 0);	
    		getRingerMode();
    		if (entering) {
    			Log.d(getClass().getSimpleName(), "entering");
    			notification.setLatestEventInfo(context, "SmartResponse Alert!", 
    					"You're entering "+name +" and your phone has been set to "+audio+"!", pendingIntent);
    			Toast.makeText(getBaseContext(),"You're entering the location '"+name +"' and your phone has been set to '"+audio+"'!",Toast.LENGTH_LONG).show();
        		
    			MessageReply.setMessageFrom("Null", name);
    			
    			if (audio.equals("Ringer")){
    				setRinger(7);
    			}
    			if (audio.equals("Vibrate")){
    				setVibrate();
    			}
    			if (audio.equals("Silent")){
    				setSilent();
    			}

    		}
    		else {
    			notification.setLatestEventInfo(context, "SmartResponse Alert!", 
    					"You're leaving "+name +", your phone's audio settings are reverting back!", pendingIntent);
    			MessageReply.setMessageFrom("Null", "--NULL--");
				Toast.makeText(getBaseContext(),"You're leaving the locatio '"+name +"', your phone's audio settings are reverting back!",Toast.LENGTH_LONG).show();
    			restoreRingerMode();
    			Log.d(getClass().getSimpleName(), "exiting");
    		}
    		notificationManager.notify(NOTIFICATION_ID, notification);
    		
    	}
    	
    	private Notification createNotification() {
    		Notification notification = new Notification();
    		
    		notification.icon = R.drawable.ic_menu_notifications;
    		notification.when = System.currentTimeMillis();
    		
    		notification.flags |= Notification.FLAG_AUTO_CANCEL;
    		notification.flags |= Notification.FLAG_SHOW_LIGHTS;
    		
    		notification.defaults |= Notification.DEFAULT_VIBRATE;
    		notification.defaults |= Notification.DEFAULT_LIGHTS;
    		
    		notification.ledARGB = Color.WHITE;
    		notification.ledOnMS = 1500;
    		notification.ledOffMS = 1500;
    		
    		return notification;
    	}
    	
    }
}
